1 逻辑门1.1 n 位与门1.1.1 写法一1.1.2 写法二1.1.3 测试代码1.2 n 位或门1.2.1 写法一1.2.2 写法二1.2.3 测试代码1.3 非门1.3.1 模块代码1.3.2 测试代码1.4 n 位与非门1.4.1 写法一1.4.2 写法二1.4.3 写法三1.4.4 测试代码1.5 n 位或非门1.5.1 写法一1.5.2 写法二1.5.3 写法三1.5.4 测试代码1.6 n 位异或门1.6.1 写法一1.6.2 写法二1.6.3 测试代码1.7 n 位同或门1.7.1 写法一1.7.2 写法二1.7.3 写法三1.7.4 测试代码2 触发器2.1 RS 触发器2.1.1 基本 RSFF2.1.2 同步 RSFF2.1.3 主从 RSFF2.1.4 测试代码2.2 D 触发器2.2.1 同步 DFF2.2.2 边沿 DFF2.2.3 测试代码2.3 JK 触发器2.3.1 同步 JKFF2.3.2 主从 JKFF2.3.3 边沿 JKFF2.3.4 测试代码2.4 T 触发器2.4.1 同步 TFF2.4.2 同步 T'FF2.4.3 测试代码3 组合逻辑电路3.1 编码器3.1.1 普通编码器1 方法一2 方法二3 方法三4 测试代码3.1.2 优先编码器1 方法一2 方法二3 方法三4 方法四5 测试代码3.2 译码器3.2.1 二进制译码器1 方法一2 方法二3 方法三4 测试代码3.2.2 七段译码管1 模块代码2 测试代码3.3 数据分配器3.3.1 模块代码3.3.2 测试代码3.4 数据选择器3.4.1 双四选一1 模块代码2 测试代码3.4.2 八选一1 模块代码2 测试代码3.5 n 位数值比较器3.5.1 模块代码3.5.2 测试代码3.6 算术运算电路3.6.1 半加器1 方法一2 方法二3 测试代码3.6.2 全加器1 方法一2 方法二3 测试代码3.6.3 半减器1 方法一2 方法二3 测试代码3.6.4 全减器1 方法一2 方法二3 方法三4 测试代码3.7 奇偶校验器3.7.1 模块代码3.7.2 测试代码4 时序逻辑电路4.1 寄存器4.1.1 n 位数码寄存器1 模块代码2 测试代码4.1.2 n 位锁存器1 模块代码2 测试代码4.1.3 n 位移位寄存器1 模块代码2 测试代码4.2 2n 分频器4.2.1 模块代码4.2.2 测试代码4.3 计数器4.3.1 n 位二进制加法计数器1 模块代码2 测试代码4.3.2 n 位二进制可逆计数器1 模块代码2 测试代码4.3.3 BCD 码 24 进制计数器1 模块代码2 测试代码4.3.4 BCD 码 60 进制计数器1 模块代码2 测试代码5 代码下载
x1// method 12module and_gate(in, out);3 parameter n 2;4 input[n1:0] in;5 output out;6
7 assign out in;8endmodule
xxxxxxxxxx1171// method 22module and_gate2(in, out);3 parameter n 2;4 input[n1:0] in;5 output out;6
7 reg temp;8 integer i;9 always @(in) begin10 temp in[0];11 for (i 1; i < n; i i 1) begin12 temp temp in[i];13 end14 end15 16 assign out temp;17endmodule
x
1// testbench of and_gate2`timescale 1ns10ps3module and_gate_tb;4 reg[2:0] in;5 wire out1, out2;6
7 and_gate #3 and_gate_1(.in(in), .out(out1));8 and_gate2 #3 and_gate_2(.in(in), .out(out2));9
10 initial begin11 in < 0;12 #200 ;13 end14
15 always #5 in < in 1;16endmodule
xxxxxxxxxx11// method 12module or_gate(in, out);3 parameter n 2;4 input[n1:0] in;5 output out;6
7 assign out in;8endmodule
xxxxxxxxxx1171// method 22module or_gate2(in, out);3 parameter n 2;4 input[n1:0] in;5 output out;6
7 reg temp;8 integer i;9 always @(in) begin10 temp in[0];11 for (i 1; i < n; i i 1) begin12 temp temp in[i];13 end14 end15
16 assign out temp;17endmodule
x
1// testbench of or_gate2`timescale 1ns10ps3module or_gate_tb;4 reg[2:0] in;5 wire out1, out2;6
7 or_gate #3 or_gate_1(.in(in), .out(out1));8 or_gate2 #3 or_gate_2(.in(in), .out(out2));9
10 initial begin11 in < 0;12 #200 ;13 end14
15 always #5 in < in 1;16endmodule
xxxxxxxxxx11// not-gate2module not_gate(in, out);3 input in;4 output out;5
6 assign out in;7endmodule
x
1// testbench of not_gate2`timescale 1ns10ps3module not_gate_tb;4 reg in;5 wire out;6
7 not_gate not_gate(.in(in), .out(out));8
9 initial begin10 in < 0;11 #10 in < 1;12 #10 ;13 end14endmodule
xxxxxxxxxx11// method 12module nand_gate(in, out);3 parameter n 2;4 input[n1:0] in;5 output out;6
7 assign out (in);8endmodule
xxxxxxxxxx1171// method 22module nand_gate2(in, out);3 parameter n 2;4 input[n1:0] in;5 output out;6
7 reg temp;8 integer i;9 always @(in) begin10 temp in[0];11 for (i 1; i < n; i i 1) begin12 temp temp in[i];13 end14 end15 16 assign out temp;17endmodule
xxxxxxxxxx1101// method 32module nand_gate3(in, out);3 parameter n 2;4 input[n1:0] in;5 output out;6
7 wire temp;8 and_gate #n and_gate_temp(.in(in), .out(temp));9 assign out temp;10endmodule
x
1// testbench of nand_gate2`timescale 1ns10ps3module nand_gate_tb;4 reg[2:0] in;5 wire out1, out2, out3;6
7 nand_gate #3 nand_gate_1(.in(in), .out(out1));8 nand_gate2 #3 nand_gate_2(.in(in), .out(out2));9 nand_gate3 #3 nand_gate_3(.in(in), .out(out3));10
11 initial begin12 in < 0;13 #200 ;14 end15
16 always #5 in < in 1;17endmodule
xxxxxxxxxx11// method 12module nor_gate(in, out);3 parameter n 2;4 input[n1:0] in;5 output out;6
7 assign out (in);8endmodule
xxxxxxxxxx1171// method 22module nor_gate2(in, out);3 parameter n 2;4 input[n1:0] in;5 output out;6
7 reg temp;8 integer i;9 always @(in) begin10 temp in[0];11 for (i 1; i < n; i i 1) begin12 temp temp in[i];13 end14 end15 16 assign out temp;17endmodule
xxxxxxxxxx1101// method 32module nor_gate3(in, out);3 parameter n 2;4 input[n1:0] in;5 output out;6
7 wire temp;8 or_gate #n or_gate_temp(.in(in), .out(temp));9 assign out temp;10endmodule
x
1// testbench of nor_gate2`timescale 1ns10ps3module nor_gate_tb;4 reg[2:0] in;5 wire out1, out2, out3;6
7 nor_gate #3 nor_gate_1(.in(in), .out(out1));8 nor_gate2 #3 nor_gate_2(.in(in), .out(out2));9 nor_gate3 #3 nor_gate_3(.in(in), .out(out3));10
11 initial begin12 in < 0;13 #200 ;14 end15
16 always #5 in < in 1;17endmodule
xxxxxxxxxx11// method 12module xor_gate(in, out);3 parameter n 2;4 input[n1:0] in;5 output out;6
7 assign out in;8endmodule
xxxxxxxxxx1171// method 22module xor_gate2(in, out);3 parameter n 2;4 input[n1:0] in;5 output out;6
7 reg temp;8 integer i;9 always @(in) begin10 temp in[0];11 for (i 1; i < n; i i 1) begin12 temp temp in[i];13 end14 end15 16 assign out temp;17endmodule
x
1// testbench of xor_gate2`timescale 1ns10ps3module xor_gate_tb;4 reg[2:0] in;5 wire out1, out2;6
7 xor_gate #3 xor_gate_1(.in(in), .out(out1));8 xor_gate2 #3 xor_gate_2(.in(in), .out(out2));9
10 initial begin11 in < 0;12 #200 ;13 end14
15 always #5 in < in 1;16endmodule
xxxxxxxxxx11// method 12module xnor_gate(in, out);3 parameter n 2;4 input[n1:0] in;5 output out;6
7 assign out (in);8endmodule
xxxxxxxxxx1171// method 22module xnor_gate2(in, out);3 parameter n 2;4 input[n1:0] in;5 output out;6
7 reg temp;8 integer i;9 always @(in) begin10 temp in[0];11 for (i 1; i < n; i i 1) begin12 temp temp in[i];13 end14 end15 16 assign out temp;17endmodule
xxxxxxxxxx1101// method 32module xnor_gate3(in, out);3 parameter n 2;4 input[n1:0] in;5 output out;6
7 wire temp;8 xor_gate #n xor_gate_temp(.in(in), .out(temp));9 assign out temp;10endmodule
x
1// testbench of xnor_gate2`timescale 1ns10ps3module xnor_gate_tb;4 reg[2:0] in;5 wire out1, out2, out3;6
7 xnor_gate #3 xnor_gate_1(.in(in), .out(out1));8 xnor_gate2 #3 xnor_gate_2(.in(in), .out(out2));9 xnor_gate3 #3 xnor_gate_3(.in(in), .out(out3));10
11 initial begin12 in < 0;13 #200 ;14 end15
16 always #5 in < in 1;17endmodule
xxxxxxxxxx1151// 1. 基本 RS 触发器2module RSFF1(S, R, Q);3 input S, R; // 低电平有效4 output reg Q;5
6 always @(S or R) begin7 if (S) begin // S 有效8 if (R) Q < 1'bx; // S 与 R 有效9 else Q < 1; // 仅 S 有效10 end11 else if (R) begin12 Q < 0; // 仅 R 有效13 end // 均无效则不变14 end15endmodule
xxxxxxxxxx1151// 2. 同步 RS 触发器2module RSFF2(S, R, CP, Q);3 input S, R, CP;4 output reg Q;5
6 always @(S or R or CP) if (CP) begin7 case ({S, R})8 2'b00: Q < 1'bx;9 2'b01: Q < 1'b1;10 2'b10: Q < 1'b0;11 2'b11: ; // Q <= Q;12 default Q < 1'bx;13 endcase14 end15endmodule
xxxxxxxxxx151// 3. 主从 RSFF2module RSFF3(S, R, CP, Q);3 input S, R, CP;4 output reg Q;5
6 reg Q1;7 always @(CP) begin8 if (CP) begin // 上升沿9 Q1 < S (RQ1:0) : (R1:1'bx);10 end11 else begin // 下降沿12 Q < Q1 1 : 0;13 end14 end15endmodule
x
1// testbench of RSFF2`timescale 1ns10ps3module RSFF_tb;4 reg S, R, CP;5 wire Q1, Q2;6
7 RSFF1 RSFF1(.S(S), .R(R), .Q(Q1));8 RSFF2 RSFF2(.S(S), .R(R), .Q(Q2), .CP(CP));9 RSFF3 RSFF3(.S(S), .R(R), .Q(Q3), .CP(CP));10
11 integer i;12 initial begin13 S < 0; R < 1; CP < 1;14 for (i 0; i < 64; i i 1) begin15 #10 {S, R} 4;16 end17 ;18 end19
20 always #10 CP < CP;21endmodule
xxxxxxxxxx11// 1. 同步 DFF (时序逻辑电路)2module DFF1(D, CP, Q);3 input D, CP;4 output reg Q;5
6 always @(D or CP) if (CP) Q < D;7endmodule
xxxxxxxxxx11// 2. 边沿 DFF2module DFF2(D, CP, Q);3 input D, CP;4 output reg Q;5
6 always @(posedge CP) Q < D;7endmodule
x
1// testbench of DFF2`timescale 1ns10ps3module DFF_tb;4 reg D, CP;5 wire Q1, Q2;6
7 DFF1 DFF1(.D(D), .CP(CP), .Q(Q1));8 DFF2 DFF2(.D(D), .CP(CP), .Q(Q2));9
10 integer i;11 initial begin12 D < 0; CP < 0;13 for (i 0; i < 16; i i 1) begin14 #10 D < 2;15 end16 ;17 end18
19 always #10 CP < CP;20endmodule
xxxxxxxxxx1231// 1. 同步 JKFF & 异步置数 & 异步清零2module JKFF1(J, K, CP, R, S, Q);3 input J, K, R, S, CP; // 只有 CP 为高电平有效4 output reg Q;5
6 always @() begin7 if (R) begin8 if (S) Q < 1'bx;9 else Q < 0;10 end11 else if (S) Q < 1;12 else if (CP) begin13 if (J) begin14 if (K) Q < Q;15 else Q < 1;16 end17 else begin18 if (K) Q < 0;19 else Q < Q;20 end21 end22 end23endmodule
xxxxxxxxxx1151// 2. 主从 JKFF2module JKFF2(J, K, CP, Q);3 input J, K, CP; // 只有 CP 为高电平有效4 output reg Q;5
6 reg Q1;7 always @(CP) begin8 if (CP) begin // 上升沿9 Q1 < J (K Q1 : 1) : (K 0 : Q1);10 end11 else begin // 下降沿12 Q < Q1 1 : 0;13 end14 end15endmodule
xxxxxxxxxx1111// 3. 边沿 JKFF2module JKFF3(J, K, CP, Q);3 input J, K, CP;4 output reg Q;5
6 always @(posedge CP) begin7 Q < (JK) J : (J Q : Q);8 // 或 Q <= (J&K) ? (~Q) : ((J|K) ? J : Q);9 // 或 Q <= J ? (K ? ~Q : 1) : (K ? 0 : Q);10 end11endmodule
x
1// testbench of JKFF2`timescale 1ns10ps3module JKFF_tb;4 reg J, K, R, S, CP;5 wire Q1, Q2, Q3;6
7 JKFF1 JKFF1(.J(J), .K(K), .R(R), .S(S), .CP(CP), .Q(Q1));8 JKFF2 JKFF2(.J(J), .K(K), .CP(CP), .Q(Q2));9 JKFF3 JKFF3(.J(J), .K(K), .CP(CP), .Q(Q3));10
11 integer i;12 initial begin13 J < 0; K < 0; R < 1; S < 1; CP < 0;14 for (i 0; i < 64; i i 1) begin15 #10 {J, K} < 4;16 end17 #10 ;18 end19
20 always #10 CP < CP;21endmodule
xxxxxxxxxx1101// 1. 同步 TFF2module TFF1(T, CP, Q, res);3 input T, CP, res; // res 为低电平有效同步清零端4 output reg Q;5
6 always @(posedge CP) begin7 if (res) Q < 0;8 else Q < T Q;9 end10endmodule
xxxxxxxxxx1101// 2. 同步 T'FF2module TFF2(CP, Q, res);3 input CP, res; // res 为低电平有效同步清零端4 output reg Q;5
6 always @(posedge CP) begin7 if (res) Q < 0;8 else Q < Q;9 end10endmodule
x
1// testbench of TFF2`timescale 1ns10ps3module TFF_tb;4 reg T, CP, res;5 wire Q1, Q2;6
7 TFF1 TFF1(.T(T), .CP(CP), .Q(Q1), .res(res));8 TFF2 TFF2(.CP(CP), .Q(Q2), .res(res));9
10 initial begin11 T < 0; CP < 0; res < 0;12 #20 res < 1;13 #100 ;14 end15
16 always #5 CP < CP;17 always #8 T < T;18endmodule
xxxxxxxxxx1491// 普通编码器 (8-3 线)2/*3- 注 1: 本文件中所有端口均为低电平有效;4- 注 2: 如果使用 Quartus 仿真, 则需要建新的文件,5 使模块名与文件名相同, 且顶层模块名与项目名相同.6- 后记: 前两种方法都挺好的, 前者清晰, 后者简洁; 最主要的是一遍写完就能跑.7 不喜欢第三种方法, 因为花了很久调试, 最后问了 new bing 才知道, 原来在8 比较 wire 型和 integer 型变量时, 需要用 $signed() 函数进行强制类型转换.9 从其它编程语言的角度来看, 第三种方法最好, 因为很容易可以扩展到更多线编码器,10 但是对于 Verilog 则不然, 使用多个模块例化后级联, 应当是更为清晰的做法.11*/12
13// 方法 1: always 块 + case 语句14module encoder1_1(sin, I, A, eout, sout);15 input sin; // 控制端 (输入使能端)16 input[7:0] I; // 编码输入, 某一时刻只能对应一个输入信号编码17 output reg eout; // 扩展端, 当且仅当控制端有效且有信号输入时有效18 output reg sout; // 选通输出端, 当且仅当控制端有效且无信号输入时有效19 output reg[2:0] A; // 编码输出, 为二进制数据20
21 always @(sin or I) if (sin) begin22 // 控制端有效, 正常编码23 if (I 8'b1111_1111) begin24 eout < 1; sout < 0;25 end // 工作时, 无输入则 sout 有效26 else begin27 eout < 0; sout < 1;28 end // 工作时, 有输入则 eout 有效29
30 case (I)31 8'b1111_1111, // 无输入与 0 输出相同32 8'b1111_1110: A < 3'b111; // 033 8'b1111_1101: A < 3'b110; // 134 8'b1111_1011: A < 3'b101; // 235 8'b1111_0111: A < 3'b100; // 336 8'b1110_1111: A < 3'b011; // 437 8'b1101_1111: A < 3'b010; // 538 8'b1011_1111: A < 3'b001; // 639 8'b0111_1111: A < 3'b000; // 740 default: A < 3'bx;41 endcase // 普通编码器不考虑其它情况42 end43 else begin44 // 控制端无效, 不进行编码45 A < 3'b111;46 eout < 1;47 sout < 1;48 end49endmodule
xxxxxxxxxx1171// 方法 2: 逻辑表达式 + assign 语句2module encoder1_2(sin, I, A, eout, sout);3 input sin; // 控制端4 input[7:0] I; // 输入端5 output eout; // 扩展端6 output sout; // 选通端7 output[2:0] A; // 输出端8
9 // 不能写成 sin | {}, 因为位数不统一10 assign A sin 3'b111 : {11 I[4] I[5] I[6] I[7], // 第三位12 I[2] I[3] I[6] I[7], // 第二位13 I[1] I[3] I[5] I[7] // 第一位14 };15 assign eout sin I;16 assign sout sin I;17endmodule
xxxxxxxxxx1381// 方法 3: always 块 + for 循环2module encoder1_3(sin, I, A, eout, sout);3 input sin; // 控制端4 input[7:0] I; // 输入端5 output reg eout; // 扩展端6 output reg sout; // 选通端7 output reg[2:0] A; // 输出端8
9 integer i;10 always @(sin or I) if (sin) begin11 // 控制端有效, 正常编码12 // 初始默认无输入13 if (I) begin14 A < 3'b111;15 eout < 1;16 sout < 0;17 end18 else begin19 A < 3'bx;20 eout < 0;21 sout < 1;22 end23 24 for (i 0; i < 8; i i 1) begin25 if ((I) (1<<i)) begin26 A < 7 i;27 eout < 0;28 sout < 1;29 end30 end31 end32 else begin33 // 控制端无效, 不进行编码34 A < 3'b111;35 eout < 1;36 sout < 1;37 end38endmodule
x
1// testbench of encoder1 (common 8-3 encoder)2`timescale 1ns10ps3module encoder1_tb;4 reg sin;5 reg[7:0] I;6 wire eout1, eout2, eout3;7 wire sout1, sout2, sout3;8 wire[2:0] A1, A2, A3;9
10 encoder1_1 encoder1_1(11 .sin(sin), .I(I), .A(A1),12 .eout(eout1), .sout(sout1)13 );14 encoder1_2 encoder1_2(15 .sin(sin), .I(I), .A(A2),16 .eout(eout2), .sout(sout2)17 );18 encoder1_3 encoder1_3(19 .sin(sin), .I(I), .A(A3),20 .eout(eout3), .sout(sout3)21 );22
23 initial begin24 sin < 0; I < 8'b0;25 #2560 sin < 1;26 #100 ;27 end28
29 always #10 I < I 1;30endmodule
xxxxxxxxxx1321// 优先编码器 (8-3 线), 即 741482// 注 1: 本文件中所有端口均为低电平有效;3// 注 2: 本文件中优先编码器均为高位优先;4
5// 方法 1: always 块 + if 语句6module encoder2_1(sin, I, A, eout, sout);7 input sin; // 控制端 (输入使能端)8 input[7:0] I; // 编码输入, 某一时刻只能对应一个输入信号编码9 output reg eout; // 扩展端, 当且仅当控制端有效且有信号输入时有效10 output reg sout; // 选通输出端, 当且仅当控制端有效且无信号输入时有效11 output reg[2:0] A; // 编码输出, 为二进制数据12
13 reg[4:0] outvec; // 为方便起见14 assign {eout, sout, A} outvec;15
16 always @(sin or I) if (sin) begin17 // 控制端有效, 正常编码18 if (I[7]) outvec < 5'b01_000;19 else if (I[6]) outvec < 5'b01_001;20 else if (I[5]) outvec < 5'b01_010;21 else if (I[4]) outvec < 5'b01_011;22 else if (I[3]) outvec < 5'b01_100;23 else if (I[2]) outvec < 5'b01_101;24 else if (I[1]) outvec < 5'b01_110;25 else if (I[0]) outvec < 5'b01_111;26 else outvec < 5'b10_111;27 end28 else begin29 // 控制端无效, 不进行编码30 outvec < 5'b11111;31 end32endmodule
xxxxxxxxxx1261// 方法 2: always 块 + for 循环2module encoder2_2(sin, I, A, eout, sout);3 input sin; // 控制端4 input[7:0] I; // 输入端5 output reg eout; // 扩展端6 output reg sout; // 选通端7 output reg[2:0] A; // 输出端8
9 integer i;10 always @(sin or I) if (sin) begin11 // 控制端有效, 正常编码12 // 默认无输入, 先赋初值13 {eout, sout} < 2'b10;14 for (i 0; i < 8; i i 1) begin15 if (I[i]) begin16 A < 7 i;17 {eout, sout} < 2'b01;18 end19 end20 end21 else begin22 // 控制端无效, 不进行编码23 A < 3'b111;24 {eout, sout} < 2'b11;25 end26endmodule
xxxxxxxxxx1201// 方法 3: assign 语句 + 条件判断2module encoder2_3(sin, I, A, eout, sout);3 input sin; // 控制端4 input[7:0] I; // 输入端5 output eout; // 扩展端6 output sout; // 选通端7 output[2:0] A; // 输出端8
9 wire[4:0] outvec; // 为了方便起见10 assign outvec I[7] 5'b01_000 :11 I[6] 5'b01_001 :12 I[5] 5'b01_010 :13 I[4] 5'b01_011 :14 I[3] 5'b01_100 :15 I[2] 5'b01_101 :16 I[1] 5'b01_110 :17 I[0] 5'b01_111 :18 5'b10_111;19 assign {eout, sout, A} sin 5'b11_111 : outvec;20endmodule
xxxxxxxxxx1251// 方法 4: assign 语句 + 逻辑表达式2module encoder2_4(sin, I, A, eout, sout);3 input sin; // 控制端4 input[7:0] I; // 输入端5 output eout; // 扩展端6 output sout; // 选通端7 output[2:0] A; // 输出端8
9 // // 或者写为 A = sin ? 3'b111 : {}10 assign A {sin, sin, sin} {11 I[7] I[6] I[5] I[4], // 第三位12 I[7] I[6] (13 I[5] I[4] I[3]14 ) (15 I[5] I[4] I[2]16 ), // 第二位17 I[7] (I[6] I[5]) (18 I[6] I[4] I[3]19 ) (20 I[6] I[4] I[2] I[1]21 ) // 第一位22 }; // 更多线的编码器可用类似的方式写出表达式23 assign eout sin I;24 assign sout sin I;25endmodule
x
1// testbench of encoder2 (priority 8-3 encoder)2`timescale 1ns10ps3module encoder2_tb;4 reg sin;5 reg[7:0] I;6 wire eout1, eout2, eout3, eout4;7 wire sout1, sout2, sout3, sout4;8 wire[2:0] A1, A2, A3, A4;9
10 encoder2_1 encoder2_1(11 .sin(sin), .I(I), .A(A1),12 .eout(eout1), .sout(sout1)13 );14 encoder2_2 encoder2_2(15 .sin(sin), .I(I), .A(A2),16 .eout(eout2), .sout(sout2)17 );18 encoder2_3 encoder2_3(19 .sin(sin), .I(I), .A(A3),20 .eout(eout3), .sout(sout3)21 );22 encoder2_4 encoder2_4(23 .sin(sin), .I(I), .A(A4),24 .eout(eout4), .sout(sout4)25 );26
27 initial begin28 sin < 0; I < 8'b0;29 #2560 sin < 1;30 #100 ;31 end32
33 always #10 I < I 1;34endmodule
xxxxxxxxxx11// 二进制 8-3 线译码器 741382// 方法 1: assign 语句 + 移位法3module decoder1_1(A, S, F);4 input[2:0] A, S; // A 为高电平输入端, S 为使能端, 3'b100 有效5 output[7:0] F; // F 为低电平输出端6
7 assign F (S 3'b100) (1'b1 << A) : (8'b0);8endmodule
xxxxxxxxxx1131// 方法 2: always 块 + 置数法2module decoder1_2(A, S, F);3 input[2:0] A, S; // A 为低电平输入端, S 为使能端, 3'b100 有效4 output reg[7:0] F; // F 为低电平输出端5
6 always @(A or S) if (S 3'b100) begin7 F (8'b0);8 F[A] 0;9 end10 else begin11 F < (8'b0);12 end13endmodule
xxxxxxxxxx1221// 方法 3: assign 语句 + case 语句2module decoder1_3(A, S, F);3 input[2:0] A, S; // A 为低电平输入端, S 为使能端, 3'b100 有效4 output reg[7:0] F; // F 为低电平输出端5
6 always @(A or S) if (S 3'b100) begin7 case (A)8 3'b000: F < 8'b1111_1110;9 3'b001: F < 8'b1111_1101;10 3'b010: F < 8'b1111_1011;11 3'b011: F < 8'b1111_0111;12 3'b100: F < 8'b1110_1111;13 3'b101: F < 8'b1101_1111;14 3'b110: F < 8'b1011_1111;15 3'b111: F < 8'b0111_1111;16 default: F < 8'bx;17 endcase18 end19 else begin20 F < (8'b0);21 end22endmodule
x
1// testbench of decoder12`timescale 1ns10ps3module decoder1_tb;4 reg[2:0] A, S;5 wire[7:0] F1, F2, F3;6
7 decoder1_1 decoder1_1(.A(A), .S(S), .F(F1));8 decoder1_2 decoder1_2(.A(A), .S(S), .F(F2));9 decoder1_3 decoder1_3(.A(A), .S(S), .F(F3));10
11 initial begin12 A < 3'b0; S < 3'b100; // 有效13 #100 S < 3'b000; // 无效14 #100 ;15 end16
17 always #10 A < A 1;18endmodule
xxxxxxxxxx1211// 七段码译码器;2module seg_dec(num, a_g);3 input[3:0] num; // 待译码、显示的数字4 output reg[6:0] a_g; // a_g --> {a, b, c, d, e, f, g}5 6 always @(num) begin7 case(num)8 4'd0: a_g < 7'b111_1110;9 4'd1: a_g < 7'b011_0000;10 4'd2: a_g < 7'b110_1101;11 4'd3: a_g < 7'b111_1001;12 4'd4: a_g < 7'b011_0011;13 4'd5: a_g < 7'b101_1011;14 4'd6: a_g < 7'b101_1111;15 4'd7: a_g < 7'b111_0000;16 4'd8: a_g < 7'b111_1111;17 4'd9: a_g < 7'b111_1001;18 default: a_g < 7'b1;19 endcase20 end21endmodule
x
1// testbench of seg_dec2`timescale 1ns10ps3module seg_dec_tb;4 reg[3:0] num;5 wire[6:0] a_g;6 7 seg_dec seg_dec(.num(num), .a_g(a_g));8 9 initial begin10 num < 0;11 #200 ;12 end13 14 always #10 num < num 1;15endmodule
xxxxxxxxxx11// 数据分配器2module demux(I, A, S, F);3 input I, S; // I 为输入端, S 为低电平控制端4 input[2:0] A; // A 为高电平控制端5 input[7:0] F; // F 为高电平输出端6
7 assign F S (8'b0 (I << A));8endmodule
x
1// testbench of demux2`timescale 1ns10ps3module demux_tb;4 reg I, S;5 reg[2:0] A;6 wire[7:0] F;7
8 demux demux(.I(I), .A(A), .S(S), .F(F));9
10 initial begin11 I < 0; S < 0; A < 3'b0;12 #200 ;13 end14
15 always #10 A < A 1;16 always #80 I < I;17 always #160 S < S;18endmodule
xxxxxxxxxx1101// 双四选一 741532module mux74153(E, Ia, Ib, A, F1, F2);3 input E; // 低电平使能端4 input[1:0] A; // 高电平控制端5 input[3:0] Ia, Ib; // 输入端6 output F1, F2; // 输出端7
8 assign F1 E Ia[A];9 assign F2 E Ib[A];10endmodule
x
1// testbench of mux741532`timescale 1ns10ps3module mux74153_tb;4 reg E;5 reg[1:0] A;6 reg[3:0] Ia, Ib;7 wire F1, F2;8
9 mux74153 mux74153(10 .E(E), .Ia(Ia), .Ib(Ib),11 .A(A), .F1(F1), .F2(F2)12 );13
14 initial begin15 E < 0; A < 2'b0;16 Ia < 4'b0001; Ib < 4'b0001;17 #200 ;18 end19
20 always #10 A < A 1;21 always #40 begin22 Ia < Ia << 1;23 Ib < Ib << 1;24 end25 always #160 E < E;26endmodule
xxxxxxxxxx11// 八选一 741512module mux74151(E, I, A, L);3 input E; // 低电平使能端4 input[2:0] A; // 高电平控制端5 input[7:0] I; // 输入端6 output L; // 输出端7
8 assign L E I[A];9endmodule
x
1// testbench of mux741512`timescale 1ns10ps3module mux74151_tb;4 reg E;5 reg[2:0] A;6 reg[7:0] I;7 wire L;8
9 mux74151 mux74151(.E(E), .I(I), .A(A), .L(L));10
11 initial begin12 E < 0; A < 3'b0;13 I < 8'b0000_0001;14 #700 ;15 end16
17 always #10 A < A 1;18 always #80 I < I << 1;19 always #640 E < E;20endmodule
xxxxxxxxxx1111// 4 位数值比较器 74852module comparactor(A, B, Ig, Ie, Il, Fg, Fe, Fl);3 parameter n 4; // 位数4 input[n1:0] A, B; // 输入5 input Ig, Ie, Il; // 级间输入, greater, equal, less6 output Fg, Fe, Fl; // 级间输出, greater, equal, less7
8 assign Fg (A > B) (A B Ig);9 assign Fe (A B) Ie;10 assign Fl (A < B) (A B Il);11endmodule
x
1// testbench of comparactor2`timescale 1ns10ps3module comparactor_tb;4 parameter n 4;5 reg[n1:0] A, B;6 reg Ig, Ie, Il;7 wire Fg, Fe, Fl;8
9 comparactor #n comparactor(10 .A(A), .B(B),11 .Ig(Ig), .Ie(Ie), .Il(Il),12 .Fg(Fg), .Fe(Fe), .Fl(Fl)13 );14
15 initial begin16 A < 4'b0; B < 4'b0;17 {Ig, Ie, Il} < 3'b000;18 #10 {Ig, Ie, Il} < 3'b001;19 #10 {Ig, Ie, Il} < 3'b010;20 #10 {Ig, Ie, Il} < 3'b100;21 #10 A < 4'b0101;22 #10 B < 4'b1010;23 #10 ;24 end25endmodule
xxxxxxxxxx11// 方法 12module HA1(A, B, S, C);3 input A, B;4 output S, C;5
6 assign S A B;7 assign C A B;8endmodule
xxxxxxxxxx11// 方法 22module HA2(A, B, S, C);3 input A, B;4 output S, C;5
6 assign {C, S} A B;7endmodule
x
1// testbench of HA2`timescale 1ns10ps3module HA_tb;4 reg A, B;5 wire S1, S2;6 wire C1, C2;7
8 HA1 HA1(.A(A), .B(B), .S(S1), .C(C1));9 HA2 HA2(.A(A), .B(B), .S(S2), .C(C2));10
11 initial begin12 A < 0; B < 0;13 #50 ;14 end15
16 always #10 {A, B} < {A, B} 1;17endmodule
xxxxxxxxxx11// 方法 12module FA1(A, B, Cin, S, Cout);3 input A, B, Cin;4 output S, Cout;5
6 assign S A B Cin;7 assign Cout (A B) Cin A B;8endmodule
xxxxxxxxxx11// 方法 22module FA2(A, B, Cin, S, Cout);3 input A, B, Cin;4 output S, Cout;5
6 assign {Cout, S} A B Cin;7endmodule
x
1// testbench of FA2`timescale 1ns10ps3module FA_tb;4 reg A, B, Cin;5 wire S1, S2;6 wire Cout1, Cout2;7
8 FA1 FA1(.A(A), .B(B), .Cin(Cin), .S(S1), .Cout(Cout1));9 FA2 FA2(.A(A), .B(B), .Cin(Cin), .S(S2), .Cout(Cout2));10
11 initial begin12 A < 0; B < 0; Cin < 0;13 #100 ;14 end15
16 always #10 {A, B, Cin} < {A, B, Cin} 1;17endmodule
xxxxxxxxxx11// 方法 12module HS1(A, B, S, C);3 input A, B;4 output S, C;5
6 assign S A B;7 assign C A B;8endmodule
xxxxxxxxxx11// 方法 22module HS2(A, B, S, C);3 input A, B;4 output S, C;5
6 assign {C, S} 2'b10 (2'b10 A B);7endmodule
x
1// testbench of HS2`timescale 1ns10ps3module HS_tb;4 reg A, B;5 wire S1, S2;6 wire C1, C2;7
8 HS1 HS1(.A(A), .B(B), .S(S1), .C(C1));9 HS2 HS2(.A(A), .B(B), .S(S2), .C(C2));10
11 initial begin12 A < 0; B < 0;13 #50 ;14 end15
16 always #10 {A, B} < {A, B} 1;17endmodule
xxxxxxxxxx11// 方法 12module FS1(A, B, C, S, Cout);3 input A, B, C;4 output S, Cout;5
6 assign S A B C;7 // 没必要列真值表, 除非是考试8 assign Cout (A B) (A C) (B C);9endmodule
xxxxxxxxxx11// 方法 22module FS2(A, B, C, S, Cout);3 input A, B, C;4 output S, Cout;5
6 assign S A B C;7 assign Cout (A (B C)) (B C);8 // 只需写一个括号: assign Cout = ~A & (B | C) | B & C;9endmodule
xxxxxxxxxx11// 方法 32module FS3(A, B, C, S, Cout);3 input A, B, C;4 output S, Cout;5
6 assign {Cout, S} 2'b10 (2 A B C);7endmodule
x
1// testbench of FS2`timescale 1ns10ps3module FS_tb;4 reg A, B, C;5 wire S1, Cout1;6 wire S2, Cout2;7 wire S3, Cout3;8
9 FS1 FS1(.A(A), .B(B), .C(C), .S(S1), .Cout(Cout1));10 FS2 FS2(.A(A), .B(B), .C(C), .S(S2), .Cout(Cout2));11 FS3 FS3(.A(A), .B(B), .C(C), .S(S3), .Cout(Cout3));12
13 initial begin14 A < 0; B < 0; C < 0;15 #100 ;16 end17
18 always #10 {A, B, C} < {A, B, C} 1;19endmodule
x
1// n 位奇偶校验器2module parity_check(I, F);3 parameter n 8; // 二进制位数4 input[n1:0] I; // 待检测的 n 位二进制数5 output reg F; // 输出二进制数的异或和6
7 integer i;8 always @() begin9 F I[0];10 for (i 1; i < n; i i 1) begin11 F F I[i];12 end13 end14endmodule
x
1// testbench of parity_check2`timescale 1ns10ps3module parity_check_tb;4 parameter n 8;5 reg[n1:0] I;6 wire F;7 parity_check parity_check(.I(I), .F(F));8
9 generate genvar i;10 for (i 0; i < n; i i 1) begin11 always #(10i10) I[i] < I[i];12 end // 用生成块遍历所有可能的情况13 endgenerate14
15 initial begin16 I < 0; // 即 n'b017 #(2n2) ; // 2 的 n 次方18 end // 两个周期后停止测试19endmodule
xxxxxxxxxx1121// n 位数码寄存器 (类似 74175, 但多了 rst)2module register1(clk, rst, D, Q);3 parameter n 4;4 input clk, rst; // 时钟脉冲, 异步清零5 input[n1:0] D; // 输入端6 output reg[n1:0] Q; // 状态, 也是输出端7
8 always @(posedge clk or negedge rst) begin9 if (rst) Q < 0;10 else Q < D;11 end12endmodule
xxxxxxxxxx1191// testbench of register12`timescale 1ns10ps3module register1_tb;4 parameter n 4;5 reg clk, rst;6 reg[n1:0] D;7 wire[n1:0] Q;8
9 register1 register1(.clk(clk), .rst(rst), .D(D), .Q(Q));10
11 initial begin12 clk < 0; rst < 1; D < 0;13 #150 rst < 0;14 #20 ;15 end16
17 always #5 clk < clk;18 always #6 D < D 1;19endmodule
xxxxxxxxxx1141// n 位锁存器 (74373)2module register2(CP, E, D, Q);3 parameter n 8;4 input CP; // 锁存信号5 input E; // 使能端口, 为 0 时有信号输出, 为 1 时输出高阻态6 input[n1:0] D; // 输入信号7 output reg[n1:0] Q; // 输出信号8
9 always @(CP or E or D) begin10 if (E) Q < 'bz; // E = 1, 输出高阻态11 else if (CP) Q < D; // CP = 0, 输入输出一致12 // CP = 1, 输出不会改变13 end14endmodule
xxxxxxxxxx1191// testbench of register22`timescale 1ns10ps3module register2_tb;4 parameter n 8;5 reg CP, E;6 reg[n1:0] D;7 wire[n1:0] Q;8
9 register2 register2(.CP(CP), .E(E), .D(D), .Q(Q));10
11 initial begin12 CP < 0; E < 0; D < 0;13 #500 ;14 end15
16 always #5 D < D 1;17 always #20 CP < CP;18 always #100 E < E;19endmodule
xxxxxxxxxx1191// n 位移位寄存器 (74194)2module register3(clk, rst, S, D, Q);3 parameter n 4;4 input clk, rst; // 时钟脉冲, 异步清零5 input[1:0] S; // {0, 0} 保持, {0, 1} 右移, {1, 0} 左移, {1, 1} 送数6 input[n1:0] D; // 置入数据7 output reg[n1:0] Q; // 输出数据8
9 always @(posedge clk or negedge rst) begin10 if (rst) Q < 0;11 else case (S)12 2'b00: Q < Q; // 不变13 2'b01: Q < Q >> 1; // 右移14 2'b10: Q < Q << 1; // 左移15 2'b11: Q < D; // 置数16 default: Q < 'bx; // 不定值17 endcase18 end19endmodule
xxxxxxxxxx1301// testbench of register32`timescale 1ns10ps3module register3_tb;4 parameter n 4;5 reg clk, rst;6 reg[1:0] S;7 reg[n1:0] D;8 wire[n1:0] Q;9
10 register3 register3(11 .clk(clk), .rst(rst),12 .S(S), .D(D), .Q(Q)13 );14
15 initial begin16 clk < 0; rst < 0;17 D < 0; S < 2'b00;18 #10 rst < 1; // 保持19 #10 S < 2'b11; // 计数20 #50 S < 2'b01; // 右移21 #50 S < 2'b11; // 计数22 #50 S < 2'b10; // 左移23 #50 S < 2'b11; // 计数24 #50 rst < 0; // 清零25 #20 ;26 end27
28 always #5 clk < clk;29 always #15 D < D 1;30endmodule
xxxxxxxxxx1251// 2n 分频器2module freqDivider(in, out, rst);3 parameter n 2; // 默认为 4 分频4 input in, rst; // 异步复位5 output reg out;6 parameter m (2n); // 位数7 reg[m1:0] cnt;8
9 always @(posedge in or negedge rst) begin10 if (rst) begin11 out < 0;12 cnt < 0;13 end14 else if (cnt n 1) begin15 out < 1;16 cnt < cnt 1;17 end18 else if (cnt 2n 1) begin19 out < 0;20 cnt < 0;21 end22 else cnt < cnt 1;23 end24endmodule
xxxxxxxxxx1191// testbench of freqDivider2`timescale 1ns10ps3module freqDivider_tb;4 reg in, rst;5 wire out1, out2;6
7 freqDivider #2 freqDivider1(.in(in), .out(ou1), .rst(rst));8 freqDivider #4 freqDivider1(.in(in), .out(ou2), .rst(rst));9
10 initial begin11 in < 0; rst < 1;12 #1 rst < 0;13 #1 rst < 1;14 #200 rst < 0;15 #20 ;16 end17
18 always #5 in < in;19endmodule
xxxxxxxxxx1191// n 位二进制计数器2module counter(clk, rst, cin, cout, Q, D, load);3 parameter n 4;4 input clk, rst; // 时钟脉冲, 异步清零5 input cin, load; // 进位输入, 同步置数6 input[n1:0] D; // 置入数据7 output cout; // 进位输出8 output reg[n1:0] Q; // 输出输出9
10 always @(posedge clk or negedge rst) begin11 if (rst) Q < 0;12 else if (cin) begin13 if (load) Q < D;14 else Q < Q 1;15 end16 end17
18 assign cout (Q (1 << n) 1);19endmodule
xxxxxxxxxx1291// testbench of counter2`timescale 1ns10ps3module counter_tb;4 parameter n 4;5 reg clk, rst;6 reg cin, load;7 reg[n1:0] D;8 wire cout;9 wire[n1:0] Q;10
11 counter #n counter(12 .clk(clk), .rst(rst),13 .cin(cin), .load(load),14 .D(D), .cout(cout), .Q(Q)15 );16
17 initial begin18 clk < 0; rst < 1;19 cin < 1; load < 1;20 D < 4'b0101;21 #1 rst < 0;22 #1 rst < 1;23 #100 load < 0;24 #8 load < 1;25 #200 ;26 end27
28 always #5 clk < clk;29endmodule
xxxxxxxxxx1211// 可逆计数器2module reversibleCounter(clk, add, rst, D, Q, load, cin, cout);3 parameter n 4;4 input clk, rst; // 时钟脉冲, 加法复位5 input add; // 为 1 则加法, 为 0 则减法6 input cin, load; // 进位输入, 同步置数7 input[n1:0] D; // 置入数据8 output reg[n1:0] Q; // 输出数据9 output cout; // 进位输出10
11 always @(posedge clk or negedge rst) begin12 if (rst) Q < 0;13 else if (cin) begin14 if (load) Q < D;15 else if (add) Q < Q 1;16 else Q < Q 1;17 end18 end19
20 assign cout (add (Q (1 << n) 1)) (add Q 0);21endmodule
xxxxxxxxxx1311// testbench of reversibleCounter2`timescale 1ns10ps3module reversibleCounter_tb;4 parameter n 4;5 reg clk, rst;6 reg add;7 reg cin, load;8 reg[n1:0] D;9 wire cout;10 wire[n1:0] Q;11
12 reversibleCounter #n reversibleCounter(13 .clk(clk), .rst(rst), .add(add),14 .cin(cin), .load(load), .D(D),15 .cout(cout), .Q(Q)16 );17
18 initial begin19 clk < 0; rst < 1;20 cin < 1; load < 1;21 add < 1; D < 4'b0101;22 #1 rst < 0;23 #1 rst < 1;24 #100 load < 0;25 #8 load < 1;26 #200 add < 0;27 #200 ;28 end29
30 always #5 clk < clk;31endmodule
xxxxxxxxxx1331// 24 进制计数器2module counter24(clk, rst, d0, d1, load, cin, cout, y0, y1);3 input clk; // 时钟信号, 上升沿触发4 input rst; // 异步清零, 低电平有效5 input[3:0] d0, d1; // 置入数据, 分别为四位6 input load; // 同步置数, 低电平有效7 input cin; // 使能端口, 高电平有效8 output cout; // 进位信号, 五十九为一9 output reg[3:0] y0, y1; // 前者个位, 后者为十位10 // 这里数字的个位与十位都采用四位二进制, 是为了方便之后译码11 // 之后将 1'd9 即 4'b1001 简写为 9, 诸如此类, 以提高易读性12
13 // 进位端口14 assign cout cin (y0 3) (y1 2);15
16 always @(posedge clk or negedge load or negedge rst) begin17 if (load) begin // 异步置数18 y0 < d0; y1 < d1;19 end20 else if (rst) begin // 异步清零21 y0 < 0; y1 < 0;22 end23 else if (cin) begin // 时钟脉冲24 if (y1 2 y0 3) begin25 y0 < 0; y1 < 0; // 23 后为 0026 end27 else if (y0 9) begin // 十位进一28 y0 < 0; y1 < y1 1;29 end30 else y0 < y0 1; // 个位进一31 end32 end33endmodule
xxxxxxxxxx1231`timescale 1ns10ps2module counter24_tb;3 reg clk, rst, load, cin;4 reg[3:0] d0, d1;5 wire[3:0] y0, y1;6 wire cout;7
8 counter24 counter24(9 .clk(clk), .rst(rst), .cin(cin),10 .d0(d0), .d1(d1), .load(load),11 .y0(y0), .y1(y1), .cout(cout)12 );13
14 initial begin15 clk < 0; rst < 1; cin < 1;16 d0 < 0; d1 < 0; load < 1;17 #10 rst < 0; // 先清零, 否则 y0 与 y1 为不定值18 #10 rst < 1; // 复位端的恢复19 #1000 ;20 end21
22 always #5 clk < clk; // 周期为 1023endmodule
xxxxxxxxxx1321// 60 进制计数器2module counter60(clk, rst, d0, d1, load, cin, cout, y0, y1);3 input clk; // 时钟信号, 上升沿触发4 input rst; // 异步清零, 低电平有效5 input[3:0] d0, d1; // 置入数据, 分别为四位6 input load; // 同步置数, 低电平有效7 input cin; // 使能端口, 高电平有效8 output cout; // 进位信号, 五十九为一9 output reg[3:0] y0, y1; // 前者个位, 后者为十位10 // 这里数字的个位与十位都采用四位二进制, 是为了方便之后译码11 // 之后将 1'd9 即 4'b1001 简写为 9, 诸如此类, 以提高易读性12
13 // 进位端口14 assign cout cin (y0 9) (y1 5);15
16 always @(posedge clk or negedge load or negedge rst) begin17 if (load) begin // 异步置数18 y0 < d0; y1 < d1;19 end20 else if (rst) begin // 异步清零21 y0 < 0; y1 < 0; // 不能写成 y0 <= y1 <= 0;22 end23 else if (cin) begin // 时钟脉冲24 if (y0 9) begin25 y0 < 0; // 进位为 026 if (y1 5) y1 < 0; // 59 后为 0027 else y1 < y1 1; // 十位进一28 end29 else y0 < y0 1; // 个位进一30 end31 end32endmodule
xxxxxxxxxx1231`timescale 1ns10ps2module counter60_tb;3 reg clk, rst, load, cin;4 reg[3:0] d0, d1;5 wire[3:0] y0, y1;6 wire cout;7
8 counter60 counter60(9 .clk(clk), .rst(rst), .cin(cin),10 .d0(d0), .d1(d1), .load(load),11 .y0(y0), .y1(y1), .cout(cout)12 );13
14 initial begin15 clk < 0; rst < 1; cin < 1;16 d0 < 0; d1 < 0; load < 1;17 #10 rst < 0; // 先清零, 否则 y0 与 y1 为不定值18 #10 rst < 1; // 复位端的恢复19 #1000 ;20 end21
22 always #5 clk < clk; // 周期为 1023endmodule